"""
目录管理器

负责统一客户端的虚拟目录树管理、路径解析和映射。
"""

from typing import Dict, List, Optional, Tuple, Any
from pathlib import Path
import json
import logging
from .base import CloudFile, FileType


class VirtualDirectoryNode:
    """虚拟目录节点"""
    
    def __init__(self, name: str, path: str, node_type: str = "virtual"):
        """
        初始化目录节点
        
        Args:
            name: 节点名称
            path: 统一路径
            node_type: 节点类型 (virtual, provider_root, provider_dir)
        """
        self.name = name
        self.path = path
        self.node_type = node_type
        self.children: Dict[str, 'VirtualDirectoryNode'] = {}
        self.parent: Optional['VirtualDirectoryNode'] = None
        
        # Provider相关信息
        self.provider_type: Optional[str] = None
        self.provider_path: Optional[str] = None
        self.mount_point: Optional[str] = None
        
        # 元数据
        self.metadata: Dict[str, Any] = {}
        self.last_sync: Optional[float] = None
    
    def add_child(self, child: 'VirtualDirectoryNode'):
        """添加子节点"""
        child.parent = self
        self.children[child.name] = child
    
    def remove_child(self, name: str) -> bool:
        """移除子节点"""
        if name in self.children:
            del self.children[name]
            return True
        return False
    
    def get_child(self, name: str) -> Optional['VirtualDirectoryNode']:
        """获取子节点"""
        return self.children.get(name)
    
    def is_virtual(self) -> bool:
        """是否为虚拟节点"""
        return self.node_type == "virtual"
    
    def is_provider_root(self) -> bool:
        """是否为provider根节点"""
        return self.node_type == "provider_root"
    
    def is_provider_node(self) -> bool:
        """是否为provider节点"""
        return self.node_type in ["provider_root", "provider_dir"]
    
    def get_full_path(self) -> str:
        """获取完整路径"""
        return self.path
    
    def to_cloud_file(self) -> CloudFile:
        """转换为CloudFile对象"""
        return CloudFile(
            file_id=self.path,
            name=self.name,
            size=0,
            file_type=FileType.FOLDER,
            path=self.path,
            parent_id=self.parent.path if self.parent else None
        )


class DirectoryManager:
    """目录管理器
    
    负责管理虚拟目录树，处理路径解析和映射。
    """
    
    def __init__(self):
        """初始化目录管理器"""
        self.logger = logging.getLogger(self.__class__.__name__)
        
        # 根节点
        self.root = VirtualDirectoryNode("/", "/", "virtual")
        
        # 路径缓存
        self._path_cache: Dict[str, VirtualDirectoryNode] = {"/": self.root}
        
        # 挂载点映射
        self._mount_points: Dict[str, Dict[str, Any]] = {}
    
    def create_mount_point(self, mount_path: str, provider_type: str, 
                          provider_config: Dict[str, Any]) -> bool:
        """
        创建挂载点
        
        Args:
            mount_path: 挂载路径，如 "/tianyi"
            provider_type: provider类型
            provider_config: provider配置
            
        Returns:
            bool: 创建是否成功
        """
        try:
            # 规范化路径
            mount_path = self._normalize_path(mount_path)
            if mount_path == "/":
                self.logger.error("不能将provider挂载到根目录")
                return False
            
            # 检查是否已存在
            if mount_path in self._mount_points:
                self.logger.warning(f"挂载点已存在: {mount_path}")
                return False
            
            # 创建目录节点
            if not self._create_directory_nodes(mount_path, provider_type):
                return False
            
            # 记录挂载点信息
            self._mount_points[mount_path] = {
                "provider_type": provider_type,
                "config": provider_config,
                "created_at": None  # 可以添加时间戳
            }
            
            self.logger.info(f"成功创建挂载点: {mount_path} -> {provider_type}")
            return True
            
        except Exception as e:
            self.logger.error(f"创建挂载点失败: {e}")
            return False
    
    def remove_mount_point(self, mount_path: str) -> bool:
        """
        移除挂载点
        
        Args:
            mount_path: 挂载路径
            
        Returns:
            bool: 移除是否成功
        """
        try:
            mount_path = self._normalize_path(mount_path)
            
            if mount_path not in self._mount_points:
                self.logger.warning(f"挂载点不存在: {mount_path}")
                return False
            
            # 移除目录节点
            self._remove_directory_nodes(mount_path)
            
            # 移除挂载点记录
            del self._mount_points[mount_path]
            
            self.logger.info(f"成功移除挂载点: {mount_path}")
            return True
            
        except Exception as e:
            self.logger.error(f"移除挂载点失败: {e}")
            return False
    
    def get_node(self, path: str) -> Optional[VirtualDirectoryNode]:
        """
        获取路径对应的节点
        
        Args:
            path: 路径
            
        Returns:
            Optional[VirtualDirectoryNode]: 节点对象
        """
        path = self._normalize_path(path)
        
        # 从缓存查找
        if path in self._path_cache:
            return self._path_cache[path]
        
        # 分解路径查找
        if path == "/":
            return self.root
        
        parts = path.strip("/").split("/")
        current_node = self.root
        
        for part in parts:
            if part in current_node.children:
                current_node = current_node.children[part]
            else:
                return None
        
        return current_node
    
    def resolve_provider_info(self, path: str) -> Tuple[Optional[str], Optional[str], Optional[str]]:
        """
        解析路径的provider信息
        
        Args:
            path: 统一路径
            
        Returns:
            Tuple: (mount_point, provider_type, provider_path)
        """
        path = self._normalize_path(path)
        
        if path == "/":
            return None, None, None
        
        # 找到对应的挂载点
        mount_point = self._find_mount_point(path)
        if not mount_point:
            return None, None, None
        
        # 获取provider类型
        mount_info = self._mount_points.get(mount_point)
        if not mount_info:
            return None, None, None
        
        provider_type = mount_info["provider_type"]
        
        # 计算provider内部路径
        if path == mount_point:
            provider_path = "/"
        else:
            provider_path = path[len(mount_point):]
            if not provider_path.startswith("/"):
                provider_path = "/" + provider_path
        
        return mount_point, provider_type, provider_path
    
    def list_virtual_children(self, path: str) -> List[VirtualDirectoryNode]:
        """
        列出虚拟目录的子节点
        
        Args:
            path: 目录路径
            
        Returns:
            List[VirtualDirectoryNode]: 子节点列表
        """
        node = self.get_node(path)
        if not node:
            return []
        
        return list(node.children.values())
    
    def resolve_path(self, path: str) -> Tuple[str, str]:
        """
        解析路径为挂载点和相对路径
        
        Args:
            path: 要解析的路径
            
        Returns:
            Tuple[str, str]: (挂载点, 相对路径)
        """
        path = self._normalize_path(path)
        
        if path == "/":
            return "/", "/"
        
        # 找到对应的挂载点
        mount_point = self._find_mount_point(path)
        if not mount_point:
            return "/", path
        
        # 计算相对路径
        if path == mount_point:
            relative_path = "/"
        else:
            relative_path = path[len(mount_point):]
            if not relative_path.startswith("/"):
                relative_path = "/" + relative_path
        
        return mount_point, relative_path
    
    def list_mount_points(self) -> List[str]:
        """
        列出所有挂载点路径
        
        Returns:
            List[str]: 挂载点路径列表
        """
        return list(self._mount_points.keys())
    
    def get_mount_points(self) -> Dict[str, Dict[str, Any]]:
        """
        获取所有挂载点信息
        
        Returns:
            Dict: 挂载点信息
        """
        return self._mount_points.copy()
    
    def is_mount_point(self, path: str) -> bool:
        """
        检查路径是否为挂载点
        
        Args:
            path: 路径
            
        Returns:
            bool: 是否为挂载点
        """
        path = self._normalize_path(path)
        return path in self._mount_points
    
    def _normalize_path(self, path: str) -> str:
        """规范化路径"""
        if not path or path == "/":
            return "/"
        
        # 移除多余的斜杠，确保以/开头但不以/结尾
        path = "/" + path.strip("/")
        
        # 处理相对路径
        parts = []
        for part in path.split("/"):
            if part and part != ".":
                if part == "..":
                    if parts:
                        parts.pop()
                else:
                    parts.append(part)
        
        return "/" + "/".join(parts) if parts else "/"
    
    def _create_directory_nodes(self, mount_path: str, provider_type: str) -> bool:
        """创建目录节点"""
        parts = mount_path.strip("/").split("/")
        current_node = self.root
        current_path = ""
        
        for i, part in enumerate(parts):
            current_path = f"{current_path}/{part}" if current_path else f"/{part}"
            
            if part not in current_node.children:
                # 判断节点类型
                is_last = (i == len(parts) - 1)
                node_type = "provider_root" if is_last else "virtual"
                
                # 创建节点
                node = VirtualDirectoryNode(part, current_path, node_type)
                
                if is_last:
                    # 设置provider信息
                    node.provider_type = provider_type
                    node.provider_path = "/"
                    node.mount_point = mount_path
                
                current_node.add_child(node)
                self._path_cache[current_path] = node
            
            current_node = current_node.children[part]
        
        return True
    
    def _remove_directory_nodes(self, mount_path: str):
        """移除目录节点"""
        # 从缓存中移除相关路径
        to_remove = [path for path in self._path_cache.keys() 
                    if path.startswith(mount_path)]
        for path in to_remove:
            del self._path_cache[path]
        
        # 从目录树中移除节点
        parts = mount_path.strip("/").split("/")
        if len(parts) == 1:
            # 直接子目录
            if parts[0] in self.root.children:
                del self.root.children[parts[0]]
        else:
            # 多级目录，需要找到父节点
            parent_path = "/" + "/".join(parts[:-1])
            parent_node = self.get_node(parent_path)
            if parent_node:
                parent_node.remove_child(parts[-1])
    
    def _find_mount_point(self, path: str) -> Optional[str]:
        """查找路径对应的挂载点"""
        # 按路径长度降序排列，优先匹配最长的挂载点
        sorted_mounts = sorted(self._mount_points.keys(), 
                             key=len, reverse=True)
        
        for mount_point in sorted_mounts:
            if path == mount_point or path.startswith(mount_point + "/"):
                return mount_point
        
        return None
    
    def save_structure(self, file_path: str) -> bool:
        """
        保存目录结构到文件
        
        Args:
            file_path: 保存文件路径
            
        Returns:
            bool: 保存是否成功
        """
        try:
            structure = {
                "mount_points": self._mount_points,
                "version": "1.0"
            }
            
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(structure, f, indent=2, ensure_ascii=False)
            
            return True
            
        except Exception as e:
            self.logger.error(f"保存目录结构失败: {e}")
            return False
    
    def load_structure(self, file_path: str) -> bool:
        """
        从文件加载目录结构
        
        Args:
            file_path: 文件路径
            
        Returns:
            bool: 加载是否成功
        """
        try:
            if not Path(file_path).exists():
                return False
            
            with open(file_path, 'r', encoding='utf-8') as f:
                structure = json.load(f)
            
            # 重建挂载点
            mount_points = structure.get("mount_points", {})
            for mount_path, mount_info in mount_points.items():
                provider_type = mount_info["provider_type"]
                provider_config = mount_info.get("config", {})
                
                self.create_mount_point(mount_path, provider_type, provider_config)
            
            return True
            
        except Exception as e:
            self.logger.error(f"加载目录结构失败: {e}")
            return False